<!--
@license
Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<link rel="import" href="../bower_components/polymer/polymer.html">

<dom-module id="shop-tabs-overlay">
  <template strip-whitespace>
    <style>
      :host {
        position: absolute;
        display: none;
        pointer-events: none;
        opacity: 0;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        transition-property: top, right, bottom, left, opacity;
      }
    </style>
  </template>
  <script>
    Polymer({
      is: 'shop-tabs-overlay',

      properties: {
        /**
         * The element the overlay should cover.
         */
        target: {
          type: Object,
          observer: '_targetChanged',
        }
      },

      listeners: {
        'transitionend': '_onTransitionend',
      },

      created: function() {
        this._lastTarget = undefined;
        this._transitionsInFlight = [];
      },

      _targetChanged: function(newTarget, oldTarget) {
        if (!this._transitionsInFlight.length) {
          if (this._lastTarget) {
            this._lastTarget.classList.remove('shop-tabs-overlay-static-above');
          }
          this.style.display = 'block';
          this._move(oldTarget, newTarget);
          this._lastTarget = this.target;
        }
      },

      _onTransitionend: function(event) {
        var index = this._transitionsInFlight.indexOf(event.propertyName);
        if (index >= 0) {
          this._transitionsInFlight.splice(index, 1);
        }

        if (!this._transitionsInFlight.length) {
          this._moveComplete();
        }
      },

      _moveComplete: function() {
        if (this._lastTarget !== this.target) {
          this._move(this._lastTarget, this.target);
          this._lastTarget = this.target;
        } else {
          if (this._lastTarget) {
            this._lastTarget.classList.add('shop-tabs-overlay-static-above');
          }
          this.style.display = 'none';
        }
      },

      _move: function(oldTarget, newTarget) {
        var from = oldTarget || newTarget;
        var to = newTarget || oldTarget;
        if (!from && !to) return;

        var fromOpacity = oldTarget ? 1 : 0;
        var toOpacity = newTarget ? 1 : 0;

        Polymer.dom.flush();
        var thisRect = this.getBoundingClientRect();
        var thisStyle = window.getComputedStyle(this);
        var fromRect = from.getBoundingClientRect();
        var toRect = to.getBoundingClientRect();

        if (toRect.top === 0 && toRect.right === 0 &&
            toRect.bottom === 0 && toRect.left === 0 &&
            toRect.width === 0 && toRect.height === 0) {
          this.style.transitionProperty = 'none';
          this.style.opacity = toOpacity;
          this._transitionsInFlight = [];
          this.async(this._moveComplete);
          return;
        } else {
          this.style.transitionProperty = '';
        }

        var top = parseFloat(thisStyle.top || '0') + (fromRect.top - thisRect.top);
        var right = parseFloat(thisStyle.right || '0') - (fromRect.right - thisRect.right);
        var bottom = parseFloat(thisStyle.bottom || '0') - (fromRect.bottom - thisRect.bottom);
        var left = parseFloat(thisStyle.left || '0') + (fromRect.left - thisRect.left);

        this.style.transitionDuration = '0s';
        this.style.transitionDelay = '0s';
        var startValues = [
          this.style.top = top + 'px',
          this.style.right = right + 'px',
          this.style.bottom = bottom + 'px',
          this.style.left = left + 'px',
          this.style.opacity = String(fromOpacity)
        ];

        top += toRect.top - fromRect.top;
        right -= toRect.right - fromRect.right;
        bottom -= toRect.bottom - fromRect.bottom;
        left += toRect.left - fromRect.left;

        var durations = [0.2, 0.2, 0.2, 0.2, 0.2];
        var delays = [0, 0, 0, 0, 0];
        // Delay left / right transitions if element is left / right of the target.
        if (fromRect.left < toRect.left && fromRect.right < toRect.right) {
          delays[3] = 0.1;
        } else if (fromRect.left > toRect.left && fromRect.right > toRect.right) {
          delays[1] = 0.1;
        }

        // Delay top / bottom transitions if element is above / below the target.
        if (fromRect.top < toRect.top && fromRect.bottom < toRect.bottom) {
          delays[0] = 0.1;
        } else if (fromRect.top > toRect.top && fromRect.bottom > toRect.bottom) {
          delays[2] = 0.1;
        }

        var endValues = [
          top + 'px',
          right + 'px',
          bottom + 'px',
          left + 'px',
          String(toOpacity)
        ];

        var names = ['top', 'right', 'bottom', 'left', 'opacity'];
        for (var i = 0; i < startValues.length; i++) {
          if (startValues[i] === endValues[i]) continue;
          if (durations[i] === 0 && delays[i] === 0) continue;
          this._transitionsInFlight.push(names[i]);
        }

        this.async(function() {
          this.style.transitionDuration = durations.map(function(x) { return x + 's'; }).join(', ');
          this.style.transitionDelay = delays.map(function(x) { return x + 's'; }).join(', ');
          this.style.top = top + 'px';
          this.style.right = right + 'px';
          this.style.bottom = bottom + 'px';
          this.style.left = left + 'px';
          this.style.opacity = String(toOpacity);
        }, 1);
      },
    });
  </script>
</dom-module>
